package com.lz.sports.service

import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.os.Build
import android.util.SparseArray
import androidx.core.util.forEach
import com.github.mjdev.libaums.UsbMassStorageDevice
import com.github.mjdev.libaums.fs.UsbFile
import com.lz.sports.LogUtils
import com.lz.sports.storage.UsbStorageDevice
import com.lz.ub.UBCConfig

/**
 * 只兼容FAT32格式的U盘
 */
@Suppress("DEPRECATION")
abstract class UsbBroadcastReceiver(private val context: Context) : BroadcastReceiver() {

    companion object {

        //后缀包
        private const val END_SUFFIX = ".zip"

        //权限
        private const val ACTION_USB_PERMISSION = "com.lz.sports.ub.USB_STORAGE_PERMISSION"
    }

    private val usbManager = context.getSystemService(Context.USB_SERVICE) as UsbManager

    //已经有权限的U盘
    private val storageDevices = SparseArray<UsbStorageDevice>()
    //没有权限的
    private val pendingStorageDevices = SparseArray<UsbStorageDevice>()

    init {
        initStorageDevices()
    }

    fun register() {
        context.registerReceiver(this, IntentFilter().apply {
            addAction(ACTION_USB_PERMISSION)
            addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED)
            addAction(UsbManager.ACTION_USB_DEVICE_DETACHED)
        })
    }

    override fun onReceive(context: Context, intent: Intent) {
        when (intent.action) {
            UsbManager.ACTION_USB_DEVICE_ATTACHED -> {
                val device = intent.extras?.getParcelable<UsbDevice>(UsbManager.EXTRA_DEVICE) ?: return
                if (!UBCConfig.isSupport(device)) {
                    onAttachedStorage()
                    storageDevices.clear()
                    pendingStorageDevices.clear()
                    initStorageDevices()
                }
            }
            UsbManager.ACTION_USB_DEVICE_DETACHED -> {
                val device = intent.extras?.getParcelable<UsbDevice>(UsbManager.EXTRA_DEVICE) ?: return
                var removeDevice = storageDevices[device.deviceId]
                if (removeDevice != null) {
                    onDetachedStorage()
                    storageDevices.remove(device.deviceId)
                    removeDevice.close()
                    return
                }
                removeDevice = pendingStorageDevices[device.deviceId]
                if (removeDevice != null) {
                    onDetachedStorage()
                    pendingStorageDevices.remove(device.deviceId)
                    return
                }
            }
            ACTION_USB_PERMISSION -> {
                val device = intent.extras?.getParcelable<UsbDevice>(UsbManager.EXTRA_DEVICE) ?: return
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    val storageDevice = pendingStorageDevices[device.deviceId]
                    if (storageDevice != null) {
                        pendingStorageDevices.remove(device.deviceId)
                        storageDevices[device.deviceId] = storageDevice
                    }
                }
            }
        }
    }

    private fun initStorageDevices() {
        for (device in UsbMassStorageDevice.getMassStorageDevices(context)) {
            if (usbManager.hasPermission(device.usbDevice)) {
                storageDevices[device.usbDevice.deviceId] = UsbStorageDevice(device)
            } else {
                pendingStorageDevices[device.usbDevice.deviceId] = UsbStorageDevice(device)
                val intent = PendingIntent.getBroadcast(
                    context, 0, Intent(ACTION_USB_PERMISSION),
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
                )
                usbManager.requestPermission(device.usbDevice, intent)
            }
        }
    }

    abstract fun onAttachedStorage()

    abstract fun onDetachedStorage()

    //清空并关闭
    private fun clear() {
        storageDevices.forEach { _, value -> value.close() }
        pendingStorageDevices.forEach { _, value -> value.close() }
    }

    fun unregisterReceiver() {
        clear()
        context.unregisterReceiver(this)
    }

    //当在子线程中支行
    fun scanFileList(): ArrayList<UsbFile> = ArrayList<UsbFile>().also {
        storageDevices.forEach { _, value ->
            val list = openStorageDevice(value)
            if (list != null && list.isNotEmpty()) it.addAll(list)
        }
    }

    //打开USB盘并扫描其中的zip文件
    private fun openStorageDevice(device: UsbStorageDevice): ArrayList<UsbFile>?  {
        try {
            LogUtils.i("openStorage ${device.getDevice().deviceName}")
            val dir = device.rootDir()
            if (dir != null) {
                return ArrayList<UsbFile>().apply { listFiles(dir, this) }
            }

            device.close()
        } catch (e: Exception) {
            LogUtils.i("open exception... ${device.getDevice().deviceName}, $e")
        }
        return null
    }

    private fun listFiles(f: UsbFile, usbFiles: ArrayList<UsbFile>) {
        if (f.isDirectory) {
            f.listFiles()?.forEach { listFiles(it, usbFiles) }
        } else if (f.length > 0 && f.name.endsWith(END_SUFFIX)) {
            usbFiles.add(f)
        }
    }
}